<template>
  <div class="bpmn-designer-container">
    <!-- 顶部操作栏 -->
    <div class="designer-header">
      <div class="header-left">
        <h2 class="bpmn-brand">BPMN Designer</h2>
      </div>

      <div class="action-buttons">
        <el-button type="primary" @click="importDiagram" icon="upload">
          {{ t('bpmn.importXml') }}
        </el-button>
        <el-button
            type="success"
            @click="saveDiagram"
            icon="document-checked"
        >
          {{ t('bpmn.save') }}
        </el-button>
        <input
            type="file"
            ref="fileInput"
            @change="handleFileUpload"
            style="display: none"
            accept=".bpmn,.xml"
        />
      </div>
    </div>

    <!-- 主设计区域 -->
    <div class="designer-content">
      <!-- 左侧工具栏容器 -->
      <div class="palette-container" ref="paletteContainer"></div>

      <!-- 中间画布 -->
      <div class="canvas-container" ref="canvas"></div>

      <!-- 右侧属性面板 -->
      <PropertiesPanel
          v-if="selectedElement"
          :element="selectedElement"
          @update="updateElementProperties"
          class="properties-panel"
      />
      <div v-else class="empty-panel">
        <el-icon><info-filled /></el-icon>
        <p>{{ t('bpmn.selectElementPrompt') }}</p>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue';
import { useI18n } from 'vue-i18n';
import BpmnModeler from 'bpmn-js/lib/Modeler';
import 'bpmn-js/dist/assets/diagram-js.css';
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
import { InfoFilled } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import CustomPalette from '@/components/flowable/CustomPalette.js';
import PropertiesPanel from '@/components/flowable/properties/PropertiesPanel.vue';

const { t } = useI18n();
// DOM引用
const canvas = ref(null);
const paletteContainer = ref(null);
const fileInput = ref(null);

// 状态变量
const bpmnModeler = ref(null);
const selectedElement = ref(null);
const contextMenu = ref({
  visible: false,
  x: 0,
  y: 0,
  element: null
});

// 初始BPMN XML
const initialBpmnXml = `<?xml version="1.0" encoding="UTF-8"?>
<definitions
  xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
  xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
  xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
  xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
  xmlns:flowable="http://flowable.org/bpmn"
  targetNamespace="http://bpmn.io/schema/bpmn">

  <process id="Process_1" isExecutable="false">
    <startEvent id="StartEvent_1" />
    <userTask id="UserTask_1" name="审批任务" />
    <endEvent id="EndEvent_1" />

    <sequenceFlow id="Flow_1" sourceRef="StartEvent_1" targetRef="UserTask_1" />
    <sequenceFlow id="Flow_2" sourceRef="UserTask_1" targetRef="EndEvent_1" />
  </process>

  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
      <bpmndi:BPMNShape id="StartEvent_1_di" bpmnElement="StartEvent_1">
        <dc:Bounds x="150" y="150" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="UserTask_1_di" bpmnElement="UserTask_1">
        <dc:Bounds x="300" y="140" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="EndEvent_1_di" bpmnElement="EndEvent_1">
        <dc:Bounds x="500" y="150" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="Flow_1_di" bpmnElement="Flow_1">
        <di:waypoint x="186" y="168" />
        <di:waypoint x="300" y="180" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_2_di" bpmnElement="Flow_2">
        <di:waypoint x="400" y="180" />
        <di:waypoint x="500" y="168" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>`;

// 组件挂载时初始化
onMounted(async () => {
  try {
    await nextTick();

    // 初始化建模器
    bpmnModeler.value = new BpmnModeler({
      container: canvas.value,
      additionalModules: [
        {
          // 使用自定义工具栏
          paletteProvider: ['type', CustomPalette]
        }
      ]
    });

    // 加载初始XML
    await bpmnModeler.value.importXML(initialBpmnXml);

    // 添加元素选择监听
    bpmnModeler.value.on('selection.changed', (event) => {
      if (event.newSelection.length > 0) {
        selectedElement.value = event.newSelection[0];
      } else {
        selectedElement.value = null;
      }
      contextMenu.value.visible = false;
    });

    // 确保渲染完成
    setTimeout(() => {
      const canvasZoom = bpmnModeler.value.get('canvas');
      canvasZoom.zoom('fit-viewport');

      // 移动工具栏到指定容器并应用样式
      const paletteEl = document.querySelector('.djs-palette');
      if (paletteEl && paletteContainer.value) {
        paletteContainer.value.appendChild(paletteEl);
        paletteEl.classList.add('custom-vertical-palette');
      }
    }, 300);

  } catch (err) {
    console.error('流程图加载失败:', err);
    ElMessage.error('流程图加载失败: ' + err.message);
  }
});

// 组件卸载前清理
onBeforeUnmount(() => {
  if (bpmnModeler.value) {
    bpmnModeler.value.destroy();
  }
});

// 更新元素属性
function updateElementProperties(properties) {
  if (!selectedElement.value) return;

  const modeling = bpmnModeler.value.get('modeling');
  const moddle = bpmnModeler.value.get('moddle');

  // 更新基本属性
  if (properties.name !== undefined || properties.documentation !== undefined) {
    modeling.updateProperties(selectedElement.value, {
      name: properties.name || ''
    });
  }

  // 更新业务对象属性
  if (properties.businessObject) {
    // 处理监听器
    if (properties.businessObject.extensionElements) {
      const extensionElements = moddle.create('bpmn:ExtensionElements', {
        values: properties.businessObject.extensionElements.values
      });
      modeling.updateProperties(selectedElement.value, {
        extensionElements
      });
    }

    // 处理其他业务属性
    modeling.updateModdleProperties(
        selectedElement.value,
        selectedElement.value.businessObject,
        properties.businessObject
    );
  }

  // 视觉反馈
  const canvas = bpmnModeler.value.get('canvas');
  canvas.addMarker(selectedElement.value.id, 'highlight-updated');
  setTimeout(() => {
    canvas.removeMarker(selectedElement.value.id, 'highlight-updated');
  }, 1000);
}

// 保存流程图
async function saveDiagram() {
  try {
    const { xml } = await bpmnModeler.value.saveXML({ format: true });
    // 实际项目中这里应该调用API保存
    console.log('BPMN XML:', xml);

    // 创建下载链接
    const blob = new Blob([xml], { type: 'application/xml' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'diagram.bpmn';
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);

    ElMessage.success({
      message: '保存成功',
      duration: 2000
    });
  } catch (err) {
    console.error('保存失败:', err);
    ElMessage.error('保存失败: ' + (err.message || '请检查控制台'));
  }
}

// 导入流程图
function importDiagram() {
  fileInput.value.click();
}

// 处理文件上传
function handleFileUpload(event) {
  const file = event.target.files[0];
  if (!file) return;

  const reader = new FileReader();
  reader.onload = async (e) => {
    try {
      await bpmnModeler.value.importXML(e.target.result);
      event.target.value = null;
      ElMessage.success('导入成功');
    } catch (err) {
      console.error('导入失败:', err);
      ElMessage.error('导入失败: 文件格式错误');
    }
  };
  reader.readAsText(file);
}
</script>

<style scoped>
.bpmn-designer-container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background: #f5f7fa;
}

.designer-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 20px;
  background: #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
  z-index: 10;
}

.header-left {
  display: flex;
  align-items: center;
}

.bpmn-brand {
  margin: 0;
  font-size: 18px;
  color: #409EFF;
}

.action-buttons {
  display: flex;
  align-items: center;
  gap: 12px;
}

.designer-content {
  display: flex;
  flex: 1;
  position: relative;
  overflow: hidden;
}

.palette-container {
  width: 50px;
  background: #f8f9fa;
  border-right: 1px solid #e4e7ed;
  z-index: 5;
  padding: 10px 0;
  position: relative;
}

.canvas-container {
  flex: 1;
  height: 100%;
  background: white;
  position: relative;
}

.properties-panel {
  width: 350px;
  min-width: 350px;

  background: #dddfdb;
}

.empty-panel {
  width: 350px;
  min-width: 350px;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: #909399;
  background: #fff;
  border-left: 1px solid #e4e7ed;
}

.empty-panel .el-icon {
  font-size: 48px;
  margin-bottom: 16px;
  color: #dcdfe6;
}

.empty-panel p {
  margin: 0;
  font-size: 14px;
  color: #606266;
}
</style>

<style>
/* 重要：引入BPMN默认样式 */
@import 'bpmn-js/dist/assets/diagram-js.css';
@import 'bpmn-js/dist/assets/bpmn-js.css';
@import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css';

.custom-vertical-palette .djs-palette-entries {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 8px;
  background: white;
  border-radius: 8px;
}

.custom-vertical-palette .entry {
  width: 40px;
  height: 40px;
  margin: 0 !important;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px !important;
  transition: all 0.2s ease;
  cursor: pointer;
  background: #f8fafc;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.custom-vertical-palette .entry:hover {
  background: #e6f7ff !important;
  transform: scale(1.05);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
}



/* 元素选中样式 */
.djs-selected .djs-outline {
  stroke: #13ce86 !important;
  stroke-width: 2px !important;
}
</style>